package com.wcs.exam.controller.admin.biz;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.wcs.exam.common.base.BaseBiz;
import com.wcs.exam.common.base.Result;
import com.wcs.exam.common.base.page.Page;
import com.wcs.exam.common.base.page.PageUtil;
import com.wcs.exam.common.config.ThreadContext;
import com.wcs.exam.common.enums.RegisterSourceEnum;
import com.wcs.exam.common.enums.TagTypeEnum;
import com.wcs.exam.common.util.BeanUtil;
import com.wcs.exam.controller.admin.req.*;
import com.wcs.exam.controller.admin.resp.AdminUsersPageResp;
import com.wcs.exam.controller.admin.resp.AdminUsersViewResp;
import com.wcs.exam.dao.TagDao;
import com.wcs.exam.dao.TagRecordDao;
import com.wcs.exam.dao.UsersDao;
import com.wcs.exam.dao.impl.mapper.entity.Tag;
import com.wcs.exam.dao.impl.mapper.entity.TagRecord;
import com.wcs.exam.dao.impl.mapper.entity.Users;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Admin-用户信息
 *
 * @author wcs
 * @since 2025-03-13
 */
@Component
@RequiredArgsConstructor
public class AdminUsersBiz extends BaseBiz {

    @NotNull
    private final UsersDao dao;
    @NotNull
    private final TagDao tagDao;
    @NotNull
    private final TagRecordDao tagRecordDao;

    /**
     * 用户信息-分页
     *
     * @param req 用户信息-分页查询参数
     * @return 用户信息
     */
    public Result<Page<AdminUsersPageResp>> page(AdminUsersPageReq req) {
        // 处理标签
        Set<Long> ids = new HashSet<>();
        if (ObjectUtil.isNotNull(req.getTagId())) {
            List<TagRecord> tagRecords = tagRecordDao.lambdaQuery().eq(TagRecord::getTagId, req.getTagId()).list();
            if (CollectionUtil.isEmpty(tagRecords)) {
                return Result.success(new Page<>());
            }
            tagRecords.forEach(item -> ids.add(item.getResourceId()));
        }

        // 处理查询条件
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<Users>()
                .in(CollectionUtil.isNotEmpty(ids), Users::getId, ids)
                .like(StrUtil.isNotBlank(req.getMobile()), Users::getMobile, req.getMobile())
                .like(StrUtil.isNotBlank(req.getNickname()), Users::getNickname, req.getNickname())
                .eq(ObjectUtil.isNotNull(req.getUserSex()), Users::getUserSex, req.getUserSex())
                .like(StrUtil.isNotBlank(req.getCity()), Users::getCity, req.getCity())
                .like(StrUtil.isNotBlank(req.getProvince()), Users::getProvince, req.getProvince())
                .like(StrUtil.isNotBlank(req.getCountry()), Users::getCountry, req.getCountry())
                .eq(ObjectUtil.isNotNull(req.getRegisterSource()), Users::getRegisterSource, req.getRegisterSource())
                .like(StrUtil.isNotBlank(req.getRealName()), Users::getRealName, req.getRealName())
                .like(StrUtil.isNotBlank(req.getIdCard()), Users::getIdCard, req.getIdCard())
                .eq(ObjectUtil.isNotNull(req.getCertificationStatus()), Users::getCertificationStatus, req.getCertificationStatus())
                .like(StrUtil.isNotBlank(req.getRemark()), Users::getRemark, req.getRemark())
                .eq(ObjectUtil.isNotNull(req.getStatus()), Users::getStatus, req.getStatus())
                // 排序
                .orderByDesc(Users::getGmtCreate)
                .orderByDesc(Users::getId);

        // 分页查询
        IPage<Users> page = dao.page(PageDTO.of(req.getPageCurrent(), req.getPageSize()), wrapper);
        Page<AdminUsersPageResp> respPage = PageUtil.transform(page, AdminUsersPageResp.class);
        if (ObjectUtil.isNull(respPage) || CollectionUtil.isEmpty(respPage.getList())) {
            return Result.success(respPage);
        }

        List<Long> userIds = respPage.getList().stream().map(AdminUsersPageResp::getId).toList();

        List<TagRecord> tagRecords = tagRecordDao.listByTagTypeAndResourceIds(TagTypeEnum.USER.getCode(), userIds);
        Map<Long, List<Long>> tagRecordMap = new HashMap<>();
        if (CollUtil.isNotEmpty(tagRecords)) {
            tagRecordMap = tagRecords.stream().collect(Collectors.groupingBy(TagRecord::getResourceId, Collectors.mapping(TagRecord::getTagId, Collectors.toList())));
        }

        for (AdminUsersPageResp resp : respPage.getList()) {
            // 脱敏处理
            resp.setMobile(DesensitizedUtil.mobilePhone(resp.getMobile()));
            // 标签集合
            resp.setTagIds(tagRecordMap.get(resp.getId()));
        }
        return Result.success(respPage);
    }

    /**
     * 用户信息-添加
     *
     * @param req 用户信息
     * @return 添加结果
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<String> save(AdminUsersSaveReq req) {
        Users users = BeanUtil.copyProperties(req, Users.class);
        users.setMobileSalt(IdUtil.simpleUUID());
        users.setMobilePsw(DigestUtil.sha1Hex(users.getMobileSalt() + req.getMobilePwd()));
        users.setRegisterSource(RegisterSourceEnum.SYS_PC.getCode());
        dao.save(users);

        // 关联标签
        handleUserTag(users, req.getTagIds());
        return Result.success(toI18nSuccess());
    }

    /**
     * 用户信息-查看
     *
     * @param id 主键ID
     * @return 用户信息
     */
    public Result<AdminUsersViewResp> view(Long id) {
        Users users = dao.getById(id);
        if (ObjectUtil.isNull(users)) {
            return Result.error("用户信息不存在");
        }
        AdminUsersViewResp resp = BeanUtil.copyProperties(users, AdminUsersViewResp.class);

        // 获取标签
        List<TagRecord> recordList = tagRecordDao.listByTagTypeAndResourceId(TagTypeEnum.USER.getCode(), users.getId());
        if (CollectionUtil.isEmpty(recordList)) {
            resp.setTags(Collections.emptyList());
        } else {
            List<Long> tagIdList = recordList.stream().map(TagRecord::getTagId).collect(Collectors.toList());
            List<Tag> tagList = tagDao.listByIds(tagIdList);
            resp.setTags(CollectionUtil.isEmpty(tagList) ? Collections.emptyList() : BeanUtil.copyProperties(tagList, AdminUsersViewResp.Tag.class));
        }
        return Result.success(resp);
    }

    /**
     * 用户信息-编辑
     *
     * @param req 用户信息-编辑对象
     * @return 编辑结果
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<String> edit(AdminUsersEditReq req) {
        // 获取校验用户信息
        Users users = dao.getById(req.getId());
        if (ObjectUtil.isNull(users)) {
            return Result.error("用户信息不存在");
        }

        // 更新用户信息
        Users updateUsers = BeanUtil.copyProperties(req, Users.class);
        updateUsers.setGmtCreate(null);
        updateUsers.setGmtModified(null);
        boolean updateRes = dao.updateById(updateUsers);

        // 清空出生时间
        if (ObjectUtil.isNull(req.getUserAge())) {
            dao.lambdaUpdate()
                    .eq(Users::getId, req.getId())
                    .set(Users::getUserAge, null)
                    .update();
        }

        // 删除用户原有标签
        tagRecordDao.deleteByTagTypeAndResourceId(TagTypeEnum.USER.getCode(), users.getId());

        // 保存用户标签
        handleUserTag(users, req.getTagIds());
        return updateRes ? Result.success(toI18nSuccess()) : Result.error(toI18nFail());
    }

    /**
     * 用户信息-更新状态
     *
     * @param req 用户信息-编辑对象
     * @return 编辑结果
     */
    public Result<String> updateStatus(AdminUsersUpdateStatusReq req) {
        // 获取校验用户信息
        Users users = dao.getById(req.getId());
        if (ObjectUtil.isNull(users)) {
            return Result.error("用户信息不存在");
        }

        // 更新用户信息
        Users updateUsers = BeanUtil.copyProperties(req, Users.class);
        updateUsers.setGmtCreate(null);
        updateUsers.setGmtModified(null);
        boolean updateRes = dao.updateById(updateUsers);
        return updateRes ? Result.success(toI18nSuccess()) : Result.error(toI18nFail());
    }

    /**
     * 用户信息-删除
     *
     * @param id ID主键
     * @return 删除结果
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<String> delete(Long id) {
        // 获取校验用户信息
        Users users = dao.getById(id);
        if (ObjectUtil.isNull(users)) {
            return Result.error("用户信息不存在");
        }

        // 删除用户信息
        dao.removeById(id);

        tagRecordDao.deleteByTagTypeAndResourceId(TagTypeEnum.USER.getCode(), id);
        return Result.success(toI18nSuccess());
    }

    /**
     * 用户信息-标签批量记录
     *
     * @param req 标签批量记录对象
     * @return 标签批量记录结果
     */
    public Result<String> tag(AdminUsersTagReq req) {
        List<Tag> tagList = tagDao.lambdaQuery().in(Tag::getId, req.getTagIds()).list();
        if (CollectionUtil.isEmpty(tagList)) {
            return Result.error("标签不存在");
        }
        // 批量保存
        List<TagRecord> tagRecordList = new ArrayList<>();
        for (Tag tag : tagList) {
            for (Long userId : req.getUserIds()) {
                TagRecord tagRecordResult = tagRecordDao.lambdaQuery().eq(TagRecord::getTagId, tag.getId()).eq(TagRecord::getResourceId, userId).one();
                if (ObjectUtil.isNull(tagRecordResult)) {
                    TagRecord tagRecord = new TagRecord();
                    tagRecord.setId(IdWorker.getId());
                    tagRecord.setTagType(tag.getTagType());
                    tagRecord.setTagId(tag.getId());
                    tagRecord.setResourceId(userId);
                    tagRecord.setCreatorId(ThreadContext.getUserId());
                    tagRecordList.add(tagRecord);
                }
            }
        }
        tagRecordDao.saveOrUpdateBatch(tagRecordList);
        return Result.success(toI18nSuccess());
    }

    /**
     * 处理用户标签保存
     *
     * @param users  店铺用户
     * @param tagIds 标签ID集合
     */
    private void handleUserTag(Users users, List<Long> tagIds) {
        // 校验标签是否为空
        if (CollectionUtil.isEmpty(tagIds)) {
            return;
        }
        List<Tag> tagList = tagDao.listByIds(tagIds);
        if (CollectionUtil.isEmpty(tagList)) {
            return;
        }

        // 批量保存用户标签
        List<TagRecord> tagRecordList = new ArrayList<>();
        for (Tag tag : tagList) {
            TagRecord tagRecord = new TagRecord();
            tagRecord.setId(IdWorker.getId());
            tagRecord.setTagType(TagTypeEnum.USER.getCode());
            tagRecord.setTagId(tag.getId());
            tagRecord.setResourceId(users.getId());
            tagRecord.setCreatorId(ThreadContext.getUserId());
            tagRecordList.add(tagRecord);
        }
        tagRecordDao.saveBatch(tagRecordList);
    }
}
